﻿
Imports osi.root.constants
Imports osi.root.delegates
Imports osi.root.template
Imports osi.root.connector
Imports osi.root.formation
Imports osi.root.utils
Imports osi.root.procedure
Imports osi.service.convertor
Imports osi.service.argument
Imports osi.service.selector
Imports osi.service.commander
Imports ss = osi.service.storage
Imports istrkeyvt_interface = osi.service.storage.istrkeyvt

Namespace allocator
    Public Class istrkeyvt
        Private Shared ReadOnly alloc As lazier(Of istrkeyvt_interface, String, String)

        Shared Sub New()
            alloc = New lazier(Of istrkeyvt_interface, String, String)()
            assert(register("memory", store.memory))
            assert(register("cached-memory", store.cached_memory))
            assert(register("memory2", store.memory2))
            assert(register("fces", store.fces))
            assert(register("file-key", store.file_key))
            assert(register("remote", store.remote))
            assert(register("balance-distributor", distributor.balance))
            assert(register("hash-distributor", distributor.hash))
            assert(register("redundance-distributor", distributor.redundance))
            assert(register("file-index", store.file_index))
            assert(register("disable", wrapper.disable))
            assert(register("timestamp-override", wrapper.timestamp_override))
            assert(register("broken", wrapper.broken))
        End Sub

        Public Shared Function register(ByVal type As String,
                                        ByVal allocator As allocator(Of istrkeyvt_interface, String)) As Boolean
            Return alloc.register(type, allocator)
        End Function

        Public Shared Function resolve(ByVal type As String,
                                       ByVal key As String,
                                       ByVal o As pointer(Of istrkeyvt_interface)) As event_comb
            Return alloc(type, key, o)
        End Function

        Public Shared Function resolve(ByVal name As String,
                                       ByVal type As String,
                                       ByVal key As String,
                                       ByVal o As pointer(Of istrkeyvt_interface)) As event_comb
            Dim ec As event_comb = Nothing
            Return New event_comb(Function() As Boolean
                                      If String.IsNullOrEmpty(name) Then
                                          Return False
                                      Else
                                          o.renew()
                                          ec = resolve(type, key, o)
                                          Return waitfor(ec) AndAlso
                                                 goto_next()
                                      End If
                                  End Function,
                                  Function() As Boolean
                                      Return ec.end_result() AndAlso
                                             assert(Not +o Is Nothing) AndAlso
                                             named_istrkeyvt.set(name, +o) AndAlso
                                             goto_end()
                                  End Function)
        End Function

        Public Class store
            Public Shared ReadOnly memory As allocator(Of istrkeyvt_interface, String)
            Public Shared ReadOnly cached_memory As allocator(Of istrkeyvt_interface, String)
            Public Shared ReadOnly memory2 As allocator(Of istrkeyvt_interface, String)
            Public Shared ReadOnly fces As allocator(Of istrkeyvt_interface, String)
            Public Shared ReadOnly file_key As allocator(Of istrkeyvt_interface, String)
            Public Shared ReadOnly remote As allocator(Of istrkeyvt_interface, String)
            Public Shared ReadOnly file_index As allocator(Of istrkeyvt_interface, String)

            Private Shared Function allocate_memory(ByVal p As var) As memory
                assert(Not p Is Nothing)
                Dim v As Int64 = 0
                If p.other_values().empty() OrElse
                   Not Int64.TryParse(p.other_values()(0), v) Then
                    Return New memory()
                Else
                    Return New memory(v)
                End If
            End Function

            Private Shared Function allocate_fces_istrkeyvt(ByVal p As var,
                                                            ByVal o As pointer(Of istrkeyvt_interface)) As event_comb
                Const type As String = "type"
                Const buff_size As String = "buff-size"
                Const max_key_count As String = "max-key-count"
                assert(Not p Is Nothing)
                Dim ec As event_comb = Nothing
                Return New event_comb(Function() As Boolean
                                          p.bind(type,
                                                 buff_size,
                                                 max_key_count)
                                          Dim bs As Int32 = 0
                                          Dim mkc As Int64 = 0
                                          bs = p.value(buff_size).to_int32(npos)
                                          mkc = p.value(max_key_count).to_int64(npos)
                                          If p.value(type).to_bool() Then
                                              ec = ss.fces.memory_fces(o, mkc)
                                          ElseIf p.other_values().empty() Then
                                              Return False
                                          ElseIf p.other_values().size() = 1 Then
                                              ec = ss.fces.ctor(o,
                                                                p.other_values()(0),
                                                                bs,
                                                                mkc)
                                          Else
                                              ec = ss.fces.ctor(o,
                                                                p.other_values()(0),
                                                                p.other_values()(1),
                                                                bs,
                                                                mkc)
                                          End If
                                          assert(Not ec Is Nothing)
                                          Return waitfor(ec) AndAlso
                                                 goto_next()
                                      End Function,
                                      Function() As Boolean
                                      Return ec.end_result() AndAlso
                                             goto_end()
                                  End Function)
            End Function

            Private Shared Function allocate_remote_istrkeyvt(
                                    ByVal v As var,
                                    ByRef o As istrkeyvt_interface,
                                    Optional ByVal allocate_tcp_questioner As  _
                                                    binder(Of _do_val_ref_ref(Of var, 
                                                                                 questioner,
                                                                                 String,
                                                                                 Boolean), 
                                                              allocate_tcp_questioner_binder_protector) = Nothing,
                                    Optional ByVal allocate_http_questioner As  _
                                                    binder(Of _do_val_ref_ref(Of var, 
                                                                                 questioner,
                                                                                 String,
                                                                                 Boolean), 
                                                              allocate_http_questioner_binder_protector) = Nothing) _
                                       As Boolean
                Const type As String = "type"
                assert(Not v Is Nothing)
                v.bind(type)
                Dim q As questioner = Nothing
                Dim target As String = Nothing
                If strsame(v.value(type), "tcp") Then
                    assert(allocate_tcp_questioner.has_value())
                    If Not (+allocate_tcp_questioner)(v, q, target) Then
                        Return False
                    End If
                Else
                    assert(allocate_http_questioner.has_value())
                    If Not (+allocate_http_questioner)(v, q, target) Then
                        Return False
                    End If
                End If
                If q Is Nothing Then
                    Return False
                ElseIf istrkeyvt_questioner.ctor(target, q, o) Then
                    Return True
                Else
                    Return False
                End If
            End Function

            Private Shared Function allocate_file_index_istrkeyvt(ByVal p As var,
                                                                  ByVal o As pointer(Of istrkeyvt_interface)) As event_comb
                Const buff_size As String = "buff-size"
                Const max_key_count As String = "max-key-count"
                assert(Not p Is Nothing)
                Dim ec As event_comb = Nothing
                Return New event_comb(Function() As Boolean
                                          If p.other_values().empty() Then
                                              Return False
                                          Else
                                              p.bind(buff_size,
                                                     max_key_count)
                                              Dim bs As Int32 = 0
                                              Dim mkc As Int64 = 0
                                              bs = p.value(buff_size).to_int32(npos)
                                              mkc = p.value(max_key_count).to_int64(npos)
                                              ec = ss.file_index.ctor(o,
                                                                      p.other_values()(0),
                                                                      bs,
                                                                      mkc)
                                              Return waitfor(ec) AndAlso
                                                     goto_next()
                                          End If
                                      End Function,
                                      Function() As Boolean
                                      Return ec.end_result() AndAlso
                                             goto_end()
                                  End Function)
            End Function

            Shared Sub New()
                memory = make_allocator(argument_allocator(Function(p As var) As istrkeyvt_interface
                                                               Return adapt(allocate_memory(p))
                                                           End Function))
                cached_memory = make_allocator(argument_allocator(Function(p As var) As istrkeyvt_interface
                                                                      Return adapt(adapter.cached(allocate_memory(p)))
                                                                  End Function))
                memory2 = make_allocator(argument_allocator(Function(p As var) As istrkeyvt_interface
                                                                assert(Not p Is Nothing)
                                                                Dim v As Int64 = 0
                                                                Dim r As memory2 = Nothing
                                                                If p.other_values().empty() OrElse
                                                                   Not Int64.TryParse(p.other_values()(0), v) Then
                                                                    r = New memory2()
                                                                Else
                                                                    r = New memory2(v)
                                                                End If
                                                                Return adapt(r)
                                                            End Function))
                fces = make_allocator(argument_allocator(Of istrkeyvt_interface)(AddressOf allocate_fces_istrkeyvt))
                file_key = make_allocator(argument_allocator(Function(p As var,
                                                                      ByRef o As istrkeyvt_interface) As Boolean
                                                                 Return assert(Not p Is Nothing) AndAlso
                                                                        Not p.other_values().empty() AndAlso
                                                                        eva(o, ss.file_key.ctor(p.other_values()(0)))
                                                             End Function))
                remote = make_allocator(argument_allocator(Of istrkeyvt_interface) _
                                                          (AddressOf allocate_remote_istrkeyvt))
                file_index = make_allocator(argument_allocator(Of istrkeyvt_interface) _
                                                              (AddressOf allocate_file_index_istrkeyvt))
            End Sub
        End Class

        Public Class distributor
            Public Shared ReadOnly balance As allocator(Of istrkeyvt_interface, String)
            Public Shared ReadOnly hash As allocator(Of istrkeyvt_interface, String)
            Public Shared ReadOnly redundance As allocator(Of istrkeyvt_interface, String)

            Private Shared Function allocate_balance_distributor(ByVal p As var) As istrkeyvt_interface
                Const update_frequence As String = "update-frequence"
                assert(Not p Is Nothing)
                p.bind(update_frequence)
                Dim uf As Int32 = 0
                If p.value(update_frequence, uf) Then
                    Return New balance_distributor(+(p.other_values()), uf)
                Else
                    Return New balance_distributor(+(p.other_values()))
                End If
            End Function

            Private Shared Function allocate_redundance_distributor(ByVal p As var) As istrkeyvt_interface
                Const verify_rate As String = "verify-rate"
                assert(Not p Is Nothing)
                p.bind(verify_rate)
                Dim vr As Int32 = 0
                If p.value(verify_rate, vr) Then
                    Return ss.redundance_distributor.ctor(+(p.other_values()), vr)
                Else
                    Return ss.redundance_distributor.ctor(+(p.other_values()))
                End If
            End Function

            Shared Sub New()
                balance = make_allocator(argument_allocator(Of istrkeyvt_interface) _
                                                           (AddressOf allocate_balance_distributor))
                hash = make_allocator(argument_allocator(Function(p As var) As istrkeyvt_interface
                                                             assert(Not p Is Nothing)
                                                             Return New hash_distributor(+(p.other_values()))
                                                         End Function))
                redundance = make_allocator(argument_allocator(Of istrkeyvt_interface) _
                                                              (AddressOf allocate_redundance_distributor))
            End Sub
        End Class

        Public Class wrapper
            Public Shared ReadOnly disable As allocator(Of istrkeyvt_interface, String)
            Public Shared ReadOnly timestamp_override As allocator(Of istrkeyvt_interface, String)
            Public Shared ReadOnly broken As allocator(Of istrkeyvt_interface, String)

            Private Shared Function allocate_disable_wrapper(ByVal p As var, ByRef o As istrkeyvt_interface) As Boolean
                Const append As String = "append"
                Const capacity As String = "capacity"
                Const delete As String = "delete"
                Const empty As String = "empty"
                Const full As String = "full"
                Const heartbeat As String = "heartbeat"
                Const keycount As String = "keycount"
                Const list As String = "list"
                Const modify As String = "modify"
                Const read As String = "read"
                Const retire As String = "retire"
                Const seek As String = "seek"
                Const sizeof As String = "sizeof"
                Const [stop] As String = "stop"
                Const unique_write As String = "unique-write"
                Const valuesize As String = "valuesize"
                assert(Not p Is Nothing)
                p.bind(append,
                       capacity,
                       delete,
                       empty,
                       full,
                       heartbeat,
                       keycount,
                       list,
                       modify,
                       read,
                       retire,
                       seek,
                       sizeof,
                       [stop],
                       unique_write,
                       valuesize)
                If p.other_values().empty() Then
                    Return False
                Else
                    o = New disable_istrkeyvt(p.switch(append),
                                              p.switch(capacity),
                                              p.switch(delete),
                                              p.switch(empty),
                                              p.switch(full),
                                              p.switch(heartbeat),
                                              p.switch(keycount),
                                              p.switch(list),
                                              p.switch(modify),
                                              p.switch(read),
                                              p.switch(retire),
                                              p.switch(seek),
                                              p.switch(sizeof),
                                              p.switch([stop]),
                                              p.switch(unique_write),
                                              p.switch(valuesize),
                                              p.other_values()(0))
                    Return True
                End If
            End Function

            Private Shared Function allocate_timestamp_override_wrapper(ByVal p As var,
                                                                        ByRef o As istrkeyvt_interface) As Boolean
                assert(Not p Is Nothing)
                If p.other_values().empty() Then
                    Return False
                Else
                    o = New timestamp_override_istrkeyvt(p.other_values()(0))
                    Return True
                End If
            End Function

            Shared Sub New()
                disable = make_allocator(argument_allocator(Of istrkeyvt_interface)(AddressOf allocate_disable_wrapper))
                timestamp_override = make_allocator(argument_allocator(Of istrkeyvt_interface) _
                                                                      (AddressOf allocate_timestamp_override_wrapper))
                broken = make_allocator(argument_allocator(Function(p As var, ByRef o As istrkeyvt_interface) As Boolean
                                                               assert(Not p Is Nothing)
                                                               If p.other_values().empty() Then
                                                                   Return False
                                                               Else
                                                                   o = New broken_istrkeyvt(p.other_values()(0))
                                                                   Return True
                                                               End If
                                                           End Function))
            End Sub
        End Class
    End Class
End Namespace
